package config

import (
	"log"
	"sync"
	"time"

	"github.com/fsnotify/fsnotify"
)

// ConfigChangeCallback 配置变更回调函数类型
type ConfigChangeCallback func(*Config)

// Watcher 配置文件监视器
type Watcher struct {
	configPath      string
	watcher         *fsnotify.Watcher
	callbacks       []ConfigChangeCallback
	callbacksMutex  sync.RWMutex
	debounceTimeout time.Duration
	lastEvent       time.Time
	stopChan        chan struct{}
	wg              sync.WaitGroup
}

// NewWatcher 创建新的配置文件监视器
func NewWatcher(configPath string) (*Watcher, error) {
	fsWatcher, err := fsnotify.NewWatcher()
	if err != nil {
		return nil, err
	}

	w := &Watcher{
		configPath:      configPath,
		watcher:         fsWatcher,
		callbacks:       make([]ConfigChangeCallback, 0),
		debounceTimeout: 1 * time.Second, // 防抖动时间间隔
		stopChan:        make(chan struct{}),
	}

	return w, nil
}

// Start 启动配置文件监视
func (w *Watcher) Start() error {
	if err := w.watcher.Add(w.configPath); err != nil {
		return err
	}

	w.wg.Add(1)
	go w.watchLoop()

	log.Printf("[INFO] 配置监控已启动，监控文件: %s", w.configPath)
	return nil
}

// Stop 停止配置文件监视
func (w *Watcher) Stop() {
	close(w.stopChan)
	w.watcher.Close()
	w.wg.Wait()
	log.Printf("[INFO] 配置监控已停止")
}

// RegisterCallback 注册配置变更回调函数
func (w *Watcher) RegisterCallback(callback ConfigChangeCallback) {
	w.callbacksMutex.Lock()
	defer w.callbacksMutex.Unlock()
	w.callbacks = append(w.callbacks, callback)
}

// watchLoop 监控循环
func (w *Watcher) watchLoop() {
	defer w.wg.Done()

	for {
		select {
		case event, ok := <-w.watcher.Events:
			if !ok {
				return
			}

			// 仅处理写入和重命名事件
			if event.Op&(fsnotify.Write|fsnotify.Create) != 0 {
				// 防抖动处理
				now := time.Now()
				if now.Sub(w.lastEvent) < w.debounceTimeout {
					continue
				}
				w.lastEvent = now

				log.Printf("[INFO] 检测到配置文件变更: %s", event.Name)

				// 重新加载配置
				newConfig, err := LoadConfig(w.configPath)
				if err != nil {
					log.Printf("[ERROR] 重新加载配置失败: %v", err)
					continue
				}

				// 触发回调
				w.callbacksMutex.RLock()
				callbacks := make([]ConfigChangeCallback, len(w.callbacks))
				copy(callbacks, w.callbacks)
				w.callbacksMutex.RUnlock()

				for _, callback := range callbacks {
					callback(newConfig)
				}
				log.Printf("[INFO] 配置已成功重新加载")
			}

		case err, ok := <-w.watcher.Errors:
			if !ok {
				return
			}
			log.Printf("[ERROR] 配置监控错误: %v", err)

		case <-w.stopChan:
			return
		}
	}
}